package com.wangjie.datastructuredesign;

import java.util.LinkedHashMap;

/**
 * @author jieshao
 * @date 2022/5/20 15:10
 *
 * 146. LRU 缓存(请你设计并实现一个满足 LRU 缓存约束的数据结构，函数 get 和 put 必须以 O(1) 的平均时间复杂度运行)
 */
public class LRUCacheExt {
    // cache
    private LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();

    // 最大容量
    private int capacity;

    /**
     * 将 key 提升为最近使用的
     *
     * @param key
     */
    private void makeRecently(int key) {
        Integer val = cache.get(key);
        // 删除 key，重新插入到链表尾部
        cache.remove(key);
        cache.put(key, val);
    }

    /**
     * 如果 key 存在于缓存中，返回 key 对应的值，否则返回 -1
     *
     * @param key
     * @return
     */
    public int get(int key) {
        if (!cache.containsKey(key)) {
            return -1;
        }
        // 将 key 变为最近使用的
        makeRecently(key);
        return cache.get(key);
    }

    /**
     * 如果 key 存在于缓存中，修改 key 对应的 val，并将 key 提升为最近使用的
     * 如果 key 不存在缓存中，若容量已满，淘汰最久未使用的 key，插入 key 和 val 为最近使用的数据
     *
     * @param key
     * @param val
     */
    public void put(int key, int val) {
        if (cache.containsKey(key)) {
            // 修改 key 的值
            cache.put(key, val);
            // 将 key 变为最近使用的
            makeRecently(key);
            return;
        }
        if (cache.size() >= this.capacity) {
            // 链表头部就是最久未使用的 key
            Integer oldestkey = cache.keySet().iterator().next();
            cache.remove(oldestkey);
        }
        // 将新的 key 添加到链表尾部
        cache.put(key, val);
    }
}